home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / internet / other / ka9q / ka9q_src.arc / TCPIN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1988-07-28  |  20.4 KB  |  808 lines

  1. /* Process incoming TCP segments. Page number references are to ARPA RFC-793,
  2.  * the TCP specification.
  3.  */
  4.  
  5. #include "global.h"
  6. #include "timer.h"
  7. #include "mbuf.h"
  8. #include "netuser.h"
  9. #include "internet.h"
  10. #include "tcp.h"
  11. #include "icmp.h"
  12. #include "iface.h"
  13. #include "ip.h"
  14.  
  15. struct tcp_stat tcp_stat;
  16.  
  17. /* This function is called from IP with the IP header in machine byte order,
  18.  * along with a mbuf chain pointing to the TCP header.
  19.  */
  20. void
  21. tcp_input(bp,protocol,source,dest,tos,length,rxbroadcast)
  22. struct mbuf *bp;    /* Data field, if any */
  23. char protocol;        /* Should always be TCP_PTCL */
  24. int32 source;        /* Remote IP address */
  25. int32 dest;        /* Our IP address */
  26. char tos;        /* Type of Service */
  27. int16 length;        /* Length of data field */
  28. char rxbroadcast;    /* Incoming broadcast - discard if true */
  29. {
  30.     void reset(),update();
  31.     void proc_syn(),send_syn(),add_reseq(),get_reseq(),unlink_tcb();
  32.  
  33.     register struct tcb *tcb;    /* TCP Protocol control block */
  34.     struct tcp seg;            /* Local copy of segment header */
  35.     struct connection conn;        /* Local copy of addresses */
  36.     struct pseudo_header ph;    /* Pseudo-header for checksumming */
  37.     int hdrlen;            /* Length of TCP header */
  38.  
  39.     if(bp == NULLBUF)
  40.         return;
  41.  
  42.     if(rxbroadcast){
  43.         /* Any TCP packet arriving as a broadcast is
  44.          * to be completely IGNORED!!
  45.          */
  46.         tcp_stat.bdcsts++;
  47.         free_p(bp);
  48.         return;
  49.     }
  50.     ph.source = source;
  51.     ph.dest = dest;
  52.     ph.protocol = protocol;
  53.     ph.length = length;
  54.     if(cksum(&ph,bp,length) != 0){
  55.         /* Checksum failed, ignore segment completely */
  56.         tcp_stat.checksum++;
  57.         free_p(bp);
  58.         return;
  59.     }
  60.     /* Form local copy of TCP header in host byte order */
  61.     if((hdrlen = ntohtcp(&seg,&bp)) < 0){
  62.         /* TCP header is too small */
  63.         tcp_stat.runt++;
  64.         free_p(bp);
  65.         return;
  66.     }
  67.     length -= hdrlen;
  68.  
  69.     /* Fill in connection structure and find TCB */
  70.     conn.local.address = dest;
  71.     conn.local.port = seg.dest;
  72.     conn.remote.address = source;
  73.     conn.remote.port = seg.source;
  74.     
  75.     if((tcb = lookup_tcb(&conn)) == NULLTCB){
  76.         struct tcb *ntcb;
  77.         void link_tcb();
  78.  
  79.         /* Check that this segment carries a SYN, and that
  80.          * there's a LISTEN on this socket with
  81.          * unspecified source address and port
  82.          */
  83.         conn.remote.address = 0;
  84.         conn.remote.port = 0;
  85.         if(!(seg.flags & SYN) || (tcb = lookup_tcb(&conn)) == NULLTCB){
  86.             /* No unspecified LISTEN either, so reject */
  87.             free_p(bp);
  88.             reset(source,dest,tos,length,&seg);
  89.             return;
  90.         }
  91.         /* We've found an server listen socket, so clone the TCB */
  92.         if(tcb->flags & CLONE){
  93.             if((ntcb = (struct tcb *)malloc(sizeof (struct tcb))) == NULLTCB){
  94.                 free_p(bp);
  95.                 /* This may fail, but we should at least try */
  96.                 reset(source,dest,tos,length,&seg);
  97.                 return;
  98.             }
  99.             ASSIGN(*ntcb,*tcb);
  100.             tcb = ntcb;
  101.             tcb->timer.arg = (char *)tcb;
  102.         } else
  103.             unlink_tcb(tcb);    /* It'll be put back on later */
  104.  
  105.         /* Stuff the foreign socket into the TCB */
  106.         tcb->conn.remote.address = source;
  107.         tcb->conn.remote.port = seg.source;
  108.  
  109.         /* NOW put on right hash chain */
  110.         link_tcb(tcb);
  111.     }
  112.     /* Do unsynchronized-state processing (p. 65-68) */
  113.     switch(tcb->state){
  114.     case CLOSED:
  115.         free_p(bp);
  116.         reset(source,dest,tos,length,&seg);
  117.         return;
  118.     case LISTEN:
  119.         if(seg.flags & RST){
  120.             free_p(bp);
  121.             return;
  122.         }
  123.         if(seg.flags & ACK){
  124.             free_p(bp);
  125.             reset(source,dest,tos,length,&seg);
  126.             return;
  127.         }
  128.         if(seg.flags & SYN){
  129.  
  130.             /* (Security check is bypassed) */
  131.             /* page 66 */
  132.             tcp_stat.conin++;
  133.             proc_syn(tcb,tos,&seg);
  134.             send_syn(tcb);
  135.             setstate(tcb,SYN_RECEIVED);        
  136.             if(length != 0 || seg.flags & FIN) {
  137.                 break;        /* Continue processing if there's more */
  138.             }
  139.             tcp_output(tcb);
  140.         }
  141.         free_p(bp);    /* Unlikely to get here directly */
  142.         return;
  143.     case SYN_SENT:
  144.         if(seg.flags & ACK){
  145.             if(!seq_within(seg.ack,tcb->iss+1,tcb->snd.nxt)){
  146.                 free_p(bp);
  147.                 reset(source,dest,tos,length,&seg);
  148.                 return;
  149.             }
  150.         }
  151.         if(seg.flags & RST){    /* p 67 */
  152.             if(seg.flags & ACK){
  153.                 /* The ack must be acceptable since we just checked it.
  154.                  * This is how the remote side refuses connect requests.
  155.                  */
  156.                 close_self(tcb,RESET);
  157.             }
  158.             free_p(bp);
  159.             return;
  160.         }
  161.         /* (Security check skipped here) */
  162.         /* Check incoming precedence; it must match if there's an ACK */
  163.         if((seg.flags & ACK) && PREC(tos) != PREC(tcb->tos)){
  164.             free_p(bp);
  165.             reset(source,dest,tos,length,&seg);
  166.             return;
  167.         }
  168.         if(seg.flags & SYN){
  169.             proc_syn(tcb,tos,&seg);
  170.             if(seg.flags & ACK){
  171.                 /* Our SYN has been acked, otherwise the ACK
  172.                  * wouldn't have been valid.
  173.                  */
  174.                 update(tcb,&seg);
  175.                 setstate(tcb,ESTABLISHED);
  176.             } else {
  177.                 setstate(tcb,SYN_RECEIVED);
  178.             }
  179.             if(length != 0 || (seg.flags & FIN)) {
  180.                 break;        /* Continue processing if there's more */
  181.             }
  182.             tcp_output(tcb);
  183.         } else {
  184.             free_p(bp);    /* Ignore if neither SYN or RST is set */
  185.         }
  186.         return;
  187.     }
  188.     /* We reach this point directly in any synchronized state. Note that
  189.      * if we fell through from LISTEN or SYN_SENT processing because of a
  190.      * data-bearing SYN, window trimming and sequence testing "cannot fail".
  191.      */
  192.  
  193.     /* Trim segment to fit receive window. */
  194.     if(trim(tcb,&seg,&bp,&length) == -1){
  195.         /* Segment is unacceptable */
  196.         if(!(seg.flags & RST)){
  197.             tcb->flags |= FORCE;
  198.             tcp_output(tcb);
  199.         }
  200.         return;
  201.     }
  202.     /* If segment isn't the next one expected, and there's data
  203.      * or flags associated with it, put it on the resequencing
  204.      * queue and return. Don't send anything in reply.
  205.      *
  206.      * Processing the ACK in an out-of-sequence segment without
  207.      * flags or data should be safe, however.
  208.      */
  209.     if(seg.seq != tcb->rcv.nxt
  210.      && (length != 0 || (seg.flags & (SYN|FIN)) )){
  211.         add_reseq(tcb,tos,&seg,bp,length);
  212.         return;
  213.     }
  214.     /* This loop first processes the current segment, and then
  215.      * repeats if it can process the resequencing queue.
  216.      */
  217.     for(;;){
  218.         /* We reach this point with an acceptable segment; all data and flags
  219.          * are in the window, and the starting sequence number equals rcv.nxt
  220.          * (p. 70)
  221.          */    
  222.         if(seg.flags & RST){
  223.             if(tcb->state == SYN_RECEIVED && !(tcb->flags & CLONE)){
  224.                 /* Go back to listen state only if this was
  225.                  * not a cloned server TCB
  226.                  */
  227.                 setstate(tcb,LISTEN);
  228.             } else {
  229.                 close_self(tcb,RESET);
  230.             }
  231.             free_p(bp);
  232.             return;
  233.         }
  234.         /* (Security check skipped here) p. 71 */
  235.         /* Check for precedence mismatch or erroneous extra SYN */
  236.         if(PREC(tos) != PREC(tcb->tos) || (seg.flags & SYN)){
  237.             free_p(bp);
  238.             reset(source,dest,tos,length,&seg);
  239.             return;
  240.         }
  241.         /* Check ack field p. 72 */
  242.         if(!(seg.flags & ACK)){
  243.             free_p(bp);    /* All segments after synchronization must have ACK */
  244.             return;
  245.         }
  246.         /* Process ACK */
  247.         switch(tcb->state){
  248.         case SYN_RECEIVED:
  249.             if(seq_within(seg.ack,tcb->snd.una+1,tcb->snd.nxt)){
  250.                 update(tcb,&seg);
  251.                 setstate(tcb,ESTABLISHED);
  252.             } else {
  253.                 free_p(bp);
  254.                 reset(source,dest,tos,length,&seg);
  255.                 return;
  256.             }
  257.             break;
  258.         case ESTABLISHED:
  259.         case CLOSE_WAIT:
  260.             update(tcb,&seg);
  261.             break;
  262.         case FINWAIT1:    /* p. 73 */
  263.             update(tcb,&seg);
  264.             if(tcb->sndcnt == 0){
  265.                 /* Our FIN is acknowledged */
  266.                 setstate(tcb,FINWAIT2);
  267.             }
  268.             break;
  269.         case FINWAIT2:
  270.             update(tcb,&seg);
  271.             break;
  272.         case CLOSING:
  273.             update(tcb,&seg);
  274.             if(tcb->sndcnt == 0){
  275.                 /* Our FIN is acknowledged */
  276.                 setstate(tcb,TIME_WAIT);
  277.                 tcb->timer.start = MSL2;
  278.                 start_timer(&tcb->timer);
  279.             }
  280.             break;
  281.         case LAST_ACK:
  282.             update(tcb,&seg);
  283.             if(tcb->sndcnt == 0){
  284.                 /* Our FIN is acknowledged, close connection */
  285.                 close_self(tcb,NORMAL);
  286.                 return;
  287.             }            
  288.         case TIME_WAIT:
  289.             tcb->flags |= FORCE;
  290.             start_timer(&tcb->timer);
  291.         }
  292.  
  293.         /* (URGent bit processing skipped here) */
  294.  
  295.         /* Process the segment text, if any, beginning at rcv.nxt (p. 74) */
  296.         if(length != 0){
  297.             switch(tcb->state){
  298.             case SYN_RECEIVED:
  299.             case ESTABLISHED:
  300.             case FINWAIT1:
  301.             case FINWAIT2:
  302.                 /* Place on receive queue */
  303.                 append(&tcb->rcvq,bp);
  304.                 tcb->rcvcnt += length;
  305.                 tcb->rcv.nxt += length;
  306.                 tcb->rcv.wnd -= length;
  307.                 tcb->flags |= FORCE;
  308.                 break;
  309.             default:
  310.                 /* Ignore segment text */
  311.                 free_p(bp);
  312.                 break;
  313.             }
  314.         }
  315.         /* If the user has set up a r_upcall function and there's
  316.          * data to be read, notify him.
  317.          *
  318.          * This is done before sending an acknowledgement,
  319.          * to give the user a chance to piggyback some reply data.
  320.          * It's also done before processing FIN so that the state
  321.          * change upcall will occur after the user has had a chance
  322.          * to read the last of the incoming data.
  323.          */
  324.         if(tcb->r_upcall && tcb->rcvcnt != 0){
  325.             (*tcb->r_upcall)(tcb,tcb->rcvcnt);
  326.         }
  327.         /* process FIN bit (p 75) */
  328.         if(seg.flags & FIN){
  329.             tcb->flags |= FORCE;    /* Always respond with an ACK */
  330.  
  331.             switch(tcb->state){
  332.             case SYN_RECEIVED:
  333.             case ESTABLISHED:
  334.                 tcb->rcv.nxt++;
  335.                 setstate(tcb,CLOSE_WAIT);
  336.                 break;
  337.             case FINWAIT1:
  338.                 tcb->rcv.nxt++;
  339.                 if(tcb->sndcnt == 0){
  340.                     /* Our FIN has been acked; bypass CLOSING state */
  341.                     setstate(tcb,TIME_WAIT);
  342.                     tcb->timer.start = MSL2;
  343.                     start_timer(&tcb->timer);
  344.                 } else {
  345.                     setstate(tcb,CLOSING);
  346.                 }
  347.                 break;
  348.             case FINWAIT2:
  349.                 tcb->rcv.nxt++;
  350.                 setstate(tcb,TIME_WAIT);
  351.                 tcb->timer.start = MSL2;
  352.                 start_timer(&tcb->timer);
  353.                 break;
  354.             case CLOSE_WAIT:
  355.             case CLOSING:
  356.             case LAST_ACK:
  357.                 break;        /* Ignore */
  358.             case TIME_WAIT:    /* p 76 */
  359.                 start_timer(&tcb->timer);
  360.                 break;
  361.             }
  362.         }
  363.         /* Scan the resequencing queue, looking for a segment we can handle,
  364.          * and freeing all those that are now obsolete.
  365.          */
  366.         while(tcb->reseq != NULLRESEQ && seq_ge(tcb->rcv.nxt,tcb->reseq->seg.seq)){
  367.             get_reseq(tcb,&tos,&seg,&bp,&length);
  368.             if(trim(tcb,&seg,&bp,&length) == 0)
  369.                 goto gotone;
  370.             /* Segment is an old one; trim has freed it */
  371.         }
  372.         break;
  373. gotone:    ;
  374.     }
  375.     tcp_output(tcb);    /* Send any necessary ack */
  376. }
  377.  
  378. /* Process an incoming ICMP response */
  379. tcp_icmp(source,dest,type,code,bpp)
  380. int32 source;        /* Original IP datagram source (i.e. us) */
  381. int32 dest;        /* Original IP datagram dest (i.e., them) */
  382. char type,code;        /* ICMP error codes */
  383. struct mbuf **bpp;    /* First 8 bytes of TCP header */
  384. {
  385.     struct tcp seg;
  386.     struct connection conn;
  387.     register struct tcb *tcb;
  388.  
  389.     /* Extract the socket info from the returned TCP header fragment
  390.      * Note that since this is a datagram we sent, the source fields
  391.      * refer to the local side.
  392.      */
  393.     ntohtcp(&seg,bpp);
  394.     conn.local.port = seg.source;
  395.     conn.remote.port = seg.dest;
  396.     conn.local.address = source;
  397.     conn.remote.address = dest;
  398.     if((tcb = lookup_tcb(&conn)) == NULLTCB)
  399.         return;    /* Unknown connection, ignore */
  400.  
  401.     /* Verify that the sequence number in the returned segment corresponds
  402.      * to something currently unacknowledged. If not, it can safely
  403.      * be ignored.
  404.      */
  405.     if(!seq_within(seg.seq,tcb->snd.una,tcb->snd.nxt))
  406.         return;
  407.  
  408.     /* The strategy here is that Destination Unreachable and Time Exceeded
  409.      * messages that occur after a connection has been established are likely
  410.      * to be transient events, and shouldn't kill our connection (at least
  411.      * until after we've tried a few more times). On the other hand, if
  412.      * they occur on our very first attempt to send a datagram on a new
  413.      * connection, they're probably "for real". In any event, the info
  414.      * is saved.
  415.      */
  416.     switch(type){
  417.     case DEST_UNREACH:
  418.     case TIME_EXCEED:
  419.         tcb->type = type;
  420.         tcb->code = code;
  421.         if(tcb->state == SYN_SENT || tcb->state == SYN_RECEIVED){
  422.             close_self(tcb,NETWORK);
  423.         }
  424.         break;
  425.     case QUENCH:
  426.         break;        /* I really ought to implement this */
  427.     }
  428. }
  429. /* Send an acceptable reset (RST) response for this segment
  430.  * The RST reply is composed in place on the input segment
  431.  */
  432. static void
  433. reset(source,dest,tos,length,seg)
  434. int32 source;    /* Remote IP address */
  435. int32 dest;    /* Our IP address */
  436. char tos;    /* Type of Service */
  437. int16 length;    /* Length of data portion */
  438. register struct tcp *seg;    /* Offending TCP header */
  439. {
  440.     struct mbuf *hbp;
  441.     struct pseudo_header ph;
  442.     int16 tmp;
  443.     char rflags;
  444.  
  445.     if(seg->flags & RST)
  446.         return;    /* Never send an RST in response to an RST */
  447.  
  448.     tcp_stat.resets++;
  449.  
  450.     /* Compose the RST IP pseudo-header, swapping addresses */
  451.     ph.source = dest;
  452.     ph.dest = source;
  453.     ph.protocol = TCP_PTCL;
  454.     ph.length = TCPLEN;
  455.  
  456.     /* Swap port numbers */
  457.     tmp = seg->dest;
  458.     seg->dest = seg->source;
  459.     seg->source = tmp;
  460.  
  461.     rflags = RST;
  462.     if(seg->flags & ACK){
  463.         /* This reset is being sent to clear a half-open connection.
  464.          * Set the sequence number of the RST to the incoming ACK
  465.          * so it will be acceptable.
  466.          */
  467.         seg->seq = seg->ack;
  468.         seg->ack = 0;
  469.     } else {
  470.         /* We're rejecting a connect request (SYN) from LISTEN state
  471.          * so we have to "acknowledge" their SYN.
  472.          */
  473.         rflags |= ACK;
  474.         seg->ack = seg->seq;
  475.         seg->seq = 0;
  476.         if(seg->flags & SYN)
  477.             seg->ack++;
  478.         seg->ack += length;
  479.         if(seg->flags & FIN)
  480.             seg->ack++;
  481.     }
  482.     seg->flags = rflags;
  483.     seg->wnd = 0;
  484.     seg->up = 0;
  485.     seg->mss = 0;
  486.     hbp = htontcp(seg,NULLBUF,&ph);
  487.     /* Ship it out (note swap of addresses) */
  488.     ip_send(dest,source,TCP_PTCL,tos,0,hbp,ph.length,0,0);
  489. }
  490.  
  491. /* Process an incoming acknowledgement and window indication.
  492.  * From page 72.
  493.  */
  494. static void
  495. update(tcb,seg)
  496. register struct tcb *tcb;
  497. register struct tcp *seg;
  498. {
  499.     int16 acked;
  500.     int32 rtt;
  501.  
  502.     acked = 0;
  503.     if(seq_gt(seg->ack,tcb->snd.nxt)){
  504.         tcb->flags |= FORCE;    /* Acks something not yet sent */
  505.         return;
  506.     }
  507.     /* Decide if we need to do a window update.
  508.      * This is always checked whenever a legal ACK is received,
  509.      * even if it doesn't actually acknowledge anything,
  510.      * because it might be a spontaneous window reopening.
  511.      */
  512.     if(seq_gt(seg->seq,tcb->snd.wl1) || ((seg->seq == tcb->snd.wl1) 
  513.      && seq_ge(seg->ack,tcb->snd.wl2))){
  514.         /* If the window had been closed, crank back the
  515.          * send pointer so we'll immediately resume transmission.
  516.          * Otherwise we'd have to wait until the next probe.
  517.          */
  518.         if(tcb->snd.wnd == 0 && seg->wnd != 0)
  519.             tcb->snd.ptr = tcb->snd.una;
  520.         tcb->snd.wnd = seg->wnd;
  521.         tcb->snd.wl1 = seg->seq;
  522.         tcb->snd.wl2 = seg->ack;
  523.     }
  524.     /* See if anything new is being acknowledged */
  525.     if(!seq_gt(seg->ack,tcb->snd.una))
  526.         return;    /* Nothing more to do */
  527.  
  528.     /* We're here, so something was acknowledged */
  529.  
  530.     /* Round trip time estimation */
  531.     if(run_timer(&tcb->rtt_timer) && seq_ge(seg->ack,tcb->rttseq)){
  532.         /* A timed sequence number has been acked */
  533.         stop_timer(&tcb->rtt_timer);
  534.         if(!(tcb->flags & RETRAN)){
  535.             /* This packet was sent only once and now
  536.              * it's been acked, so compute the new smoothed
  537.              * estimate.
  538.              */
  539.             rtt = tcb->rtt_timer.start - tcb->rtt_timer.count;
  540.             rtt *= MSPTICK;
  541.             /* Fast attack/slow decay algorithm by Dave Mills
  542.              * (see RFC-889)
  543.              */
  544.             if(rtt > tcb->srtt){
  545.                 /* RTT is increasing, use fast attack */
  546.                 tcb->srtt = (ALPHA1*tcb->srtt + rtt)/(ALPHA1+1);
  547.             } else {
  548.                 /* RTT is decreasing, use slow decay */
  549.                 tcb->srtt = (ALPHA2*tcb->srtt + rtt)/(ALPHA2+1);
  550.             }
  551.             /* Now update the retransmission timeout */
  552.             tcb->backoff = 0;
  553. #ifdef    notdef
  554.             tcb->timer.start = (BETA * tcb->srtt)/MSPTICK;
  555.             /* Never initialize the timer with zero; it won't run! */
  556.             tcb->timer.start = max(tcb->timer.start,1);
  557. #endif
  558.             tcb->timer.start = BETA * max(tcb->srtt,1) / MSPTICK;
  559.         }
  560.     }
  561.     /* We're here, so the ACK must have actually acked something */
  562.     acked = seg->ack - tcb->snd.una;
  563.  
  564.     /* If we're waiting for an ack of our SYN, process it */
  565.     switch(tcb->state){
  566.     case SYN_SENT:
  567.     case SYN_RECEIVED:
  568.         acked--;
  569.         tcb->sndcnt--;
  570.     }
  571.     /* Remove acknowledged bytes from the send queue and update the
  572.      * unacknowledged pointer. If a FIN is being acked,
  573.      * pullup won't be able to remove it from the queue.
  574.      */
  575.     pullup(&tcb->sndq,NULLCHAR,acked);
  576.  
  577.     /* This will include the FIN if there is one */
  578.     tcb->sndcnt -= acked;
  579.     tcb->snd.una = seg->ack;
  580.  
  581.     /* Stop retransmission timer, but restart it if there is still
  582.      * unacknowledged data.
  583.      */    
  584.     stop_timer(&tcb->timer);
  585.     if(tcb->snd.una != tcb->snd.nxt)
  586.         start_timer(&tcb->timer);
  587.  
  588.     /* If retransmissions have been occurring, make sure the
  589.      * send pointer doesn't repeat ancient history
  590.      */
  591.     if(seq_lt(tcb->snd.ptr,tcb->snd.una))
  592.         tcb->snd.ptr = tcb->snd.una;
  593.  
  594.     /* Clear the retransmission flag since the oldest
  595.      * unacknowledged segment (the only one that is ever retransmitted)
  596.      * has now been acked.
  597.      */
  598.     tcb->flags &= ~RETRAN;
  599.  
  600.     /* If outgoing data was acked, notify the user so he can send more
  601.      * unless we've already sent a FIN.
  602.      */
  603.     if(acked != 0 && tcb->t_upcall){
  604.         switch(tcb->state){
  605.          case ESTABLISHED:
  606.         case CLOSE_WAIT:
  607.             (*tcb->t_upcall)(tcb,tcb->window - tcb->sndcnt);
  608.         }
  609.     }
  610. }
  611.  
  612. /* Determine if the given sequence number is in our receiver window.
  613.  * NB: must not be used when window is closed!
  614.  */
  615. static
  616. int
  617. in_window(tcb,seq)
  618. struct tcb *tcb;
  619. int32 seq;
  620. {
  621.     return seq_within(seq,tcb->rcv.nxt,(int32)(tcb->rcv.nxt+tcb->rcv.wnd-1));
  622. }
  623.  
  624. /* Process an incoming SYN */
  625. static void
  626. proc_syn(tcb,tos,seg)
  627. register struct tcb *tcb;
  628. char tos;
  629. struct tcp *seg;
  630. {
  631.     int16 mtu,ip_mtu();
  632.  
  633.     tcb->flags |= FORCE;    /* Always send a response */
  634.  
  635.     /* Note: It's not specified in RFC 793, but SND.WL1 and
  636.      * SND.WND are initialized here since it's possible for the
  637.      * window update routine in update() to fail depending on the
  638.      * IRS if they are left unitialized.
  639.      */
  640.     /* Check incoming precedence and increase if higher */
  641.     if(PREC(tos) > PREC(tcb->tos))
  642.         tcb->tos = tos;
  643.     tcb->rcv.nxt = seg->seq + 1;    /* p 68 */
  644.     tcb->snd.wl1 = tcb->irs = seg->seq;
  645.     tcb->snd.wnd = seg->wnd;
  646.     if(seg->mss != 0)
  647.         tcb->mss = seg->mss;
  648.     /* Check the MTU of the interface we'll use to reach this guy
  649.      * and lower the MSS so that unnecessary fragmentation won't occur
  650.      */
  651.     if((mtu = ip_mtu(tcb->conn.remote.address)) != 0){
  652.         /* Allow space for the TCP and IP headers */
  653.         mtu -= TCPLEN + IPLEN;
  654.         tcb->mss = min(mtu,tcb->mss);
  655.     }
  656. }
  657.  
  658. /* Generate an initial sequence number and put a SYN on the send queue */
  659. void
  660. send_syn(tcb)
  661. register struct tcb *tcb;
  662. {
  663.     tcb->iss = iss();
  664.     tcb->rttseq = tcb->snd.wl2 = tcb->snd.una = tcb->iss;
  665.     tcb->snd.ptr = tcb->snd.nxt = tcb->rttseq;
  666.     tcb->sndcnt++;
  667.     tcb->flags |= FORCE;
  668. }
  669.  
  670. /* Add an entry to the resequencing queue in the proper place */
  671. static void
  672. add_reseq(tcb,tos,seg,bp,length)
  673. struct tcb *tcb;
  674. char tos;
  675. struct tcp *seg;
  676. struct mbuf *bp;
  677. int16 length;
  678. {
  679.     register struct reseq *rp,*rp1;
  680.  
  681.     /* Allocate reassembly descriptor */
  682.     if((rp = (struct reseq *)malloc(sizeof (struct reseq))) == NULLRESEQ){
  683.         /* No space, toss on floor */
  684.         free_p(bp);
  685.         return;
  686.     }
  687.     ASSIGN(rp->seg,*seg);
  688.     rp->tos = tos;
  689.     rp->bp = bp;
  690.     rp->length = length;
  691.  
  692.     /* Place on reassembly list sorting by starting seq number */
  693.     rp1 = tcb->reseq;
  694.     if(rp1 == NULLRESEQ || seq_lt(seg->seq,rp1->seg.seq)){
  695.         /* Either the list is empty, or we're less than all other
  696.          * entries; insert at beginning.
  697.          */
  698.         rp->next = rp1;
  699.         tcb->reseq = rp;
  700.     } else {
  701.         /* Find the last entry less than us */
  702.         for(;;){
  703.             if(rp1->next == NULLRESEQ || seq_lt(seg->seq,rp1->next->seg.seq)){
  704.                 /* We belong just after this one */
  705.                 rp->next = rp1->next;
  706.                 rp1->next = rp;
  707.                 break;
  708.             }
  709.             rp1 = rp1->next;
  710.         }
  711.     }
  712. }
  713.  
  714. /* Fetch the first entry off the resequencing queue */
  715. static void
  716. get_reseq(tcb,tos,seg,bp,length)
  717. register struct tcb *tcb;
  718. char *tos;
  719. struct tcp *seg;
  720. struct mbuf **bp;
  721. int16 *length;
  722. {
  723.     register struct reseq *rp;
  724.  
  725.     if((rp = tcb->reseq) == NULLRESEQ)
  726.         return;
  727.  
  728.     tcb->reseq = rp->next;
  729.  
  730.     *tos = rp->tos;
  731.     ASSIGN(*seg,rp->seg);
  732.     *bp = rp->bp;
  733.     *length = rp->length;
  734.     free((char *)rp);
  735. }
  736.  
  737. /* Trim segment to fit window. Return 0 if OK, -1 if segment is
  738.  * unacceptable.
  739.  */
  740. static int
  741. trim(tcb,seg,bp,length)
  742. register struct tcb *tcb;
  743. register struct tcp *seg;
  744. struct mbuf **bp;
  745. int16 *length;
  746. {
  747.     struct mbuf *nbp;
  748.     long dupcnt,excess;
  749.     int16 len;        /* Segment length including flags */
  750.     char accept;
  751.  
  752.     accept = 0;
  753.     len = *length;
  754.     if(seg->flags & SYN)
  755.         len++;
  756.     if(seg->flags & FIN)
  757.         len++;
  758.  
  759.     /* Acceptability tests */
  760.     if(tcb->rcv.wnd == 0){
  761.         /* Only in-order, zero-length segments are acceptable when our window
  762.          * is closed.
  763.          */
  764.         if(seg->seq == tcb->rcv.nxt && len == 0){
  765.             return 0;    /* Acceptable, no trimming needed */
  766.         }
  767.     } else {
  768.         /* Some part of the segment must be in the window */
  769.         if(in_window(tcb,seg->seq)){
  770.             accept++;    /* Beginning is */
  771.         } else if(len != 0){
  772.             if(in_window(tcb,(int32)(seg->seq+len-1)) || /* End is */
  773.              seq_within(tcb->rcv.nxt,seg->seq,(int32)(seg->seq+len-1))){ /* Straddles */
  774.                 accept++;
  775.             }
  776.         }
  777.     }
  778.     if(!accept){
  779.         free_p(*bp);
  780.         return -1;
  781.     }
  782.     dupcnt = tcb->rcv.nxt - seg->seq;
  783.     if(dupcnt > 0){
  784.         /* Trim off SYN if present */
  785.         if(seg->flags & SYN){
  786.             /* SYN is before first data byte */
  787.             seg->flags &= ~SYN;
  788.             seg->seq++;
  789.             dupcnt--;
  790.         }
  791.         if(dupcnt > 0){
  792.             pullup(bp,NULLCHAR,(int16)dupcnt);
  793.             seg->seq += dupcnt;
  794.             *length -= dupcnt;
  795.         }
  796.     }
  797.     excess = seg->seq + *length - (tcb->rcv.nxt + tcb->rcv.wnd);
  798.     if(excess > 0){
  799.         /* Trim right edge */
  800.         *length -= excess;
  801.         nbp = copy_p(*bp,*length);
  802.         free_p(*bp);
  803.         *bp = nbp;
  804.         seg->flags &= ~FIN;    /* FIN follows last data byte */
  805.     }
  806.     return 0;
  807. }
  808.